/**
 * a class that controls the download of multiple loaders
 */

package ch.sfug.net.loader {
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	
	import ch.sfug.net.loader.AbstractLoader;	

	public class QueueLoader extends EventDispatcher {

		protected var queue:Array;
		protected var activ:Number;
		private var _run:Boolean;

		public function QueueLoader() {
			super();
			queue = new Array();
		}

		
		/**
		 * starts to download the queue
		 */
		public function start(  ):void {
			activ = 0;
			loadStart();
			loadNext();
		}

		
		
		
		/**
		 * adds a loader to the queue
		 */
		public function addLoader( l:AbstractLoader ):void {
			if( l != null ) {
				queue.push(l);
			}
		}

		
		/**
		 * removes all loaders from the queue
		 */
		public function removeLoaders(  ):void {
			queue = new Array();
		}

		
		/**
		 * stops the loaders
		 */
		public function stop(  ):void {
			if( running ) {
				var loader:AbstractLoader = AbstractLoader(queue[ activ - 1 ]);
				if( loader != null ) {
					loader.removeEventListener(Event.COMPLETE, onLoaded);
					loader.removeEventListener( ErrorEvent.ERROR, onError );
					loader.removeEventListener(IOErrorEvent.IO_ERROR, onError );
					loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onError );
					loader.stop();
				}
			}
			activ = 0;
			_run = false;
		}

		
		/**
		 * returns the array of the loaders
		 */
		public function get loaders(  ):Array {
			return this.queue;
		}

		
		/**
		 * returns true when the queueloader is running
		 */
		public function get running(  ):Boolean {
			return _run;
		}

		
		/**
		 * catches the event from a loader when its finished with loading
		 */
		private function onLoaded( evt:Event ):void {

			var loader:AbstractLoader = AbstractLoader(evt.target);
			loader.removeEventListener(Event.COMPLETE, onLoaded);
			loader.removeEventListener( ErrorEvent.ERROR, onError );
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onError );
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onError );

			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, activ, queue.length) );
			loadNext();
		}

		
		/**
		 * loads the next loader.
		 */
		protected function loadNext():void {

			if( queue.length > activ && running ) {
				var loader:AbstractLoader = AbstractLoader(queue[ activ ]);
				activ++;
				loader.addEventListener(Event.COMPLETE, onLoaded);
				loader.addEventListener( ErrorEvent.ERROR, onError );
				loader.addEventListener(IOErrorEvent.IO_ERROR, onError );
				loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError );
				loader.load();
			} else {
				loadEnd();
			}
		}
		
		
		private function onError(event:Event):void {
			dispatchEvent(event);
		}

		
		/**
		 * dispatches the open event. and sets the run state to true.
		 */
		protected function loadStart():void {
			_run = true;
			dispatchEvent(new Event(Event.OPEN));
		}

		
		/**
		 * dispatches the complete event. and sets the run state to false.
		 */
		protected function loadEnd():void {
			_run = false;
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}
}